import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import javax.swing.SwingUtilities;

public class ConnectionPoolConnectionHandler extends Thread {
    
    // Listening port for connection acceptance
    public int port;
    // The server socket
    public static ServerSocket server_socket;
    // The minimum of threads prepared to handle requests
    public int min;
    // The threshold which when reached, makes the minimum step up to this value
    public int threshold;
    // The maximum number of total connections
    public int max;
    
    /**
     * Connection Pool Handler Constructor
     *
     * @param port Server socket port number
     * @param min Minimum number of threads in the connection pool
     * @param threshold Threshold of the connection pool
     * @param max Maximum number of threads in the connection pool
     */
    public ConnectionPoolConnectionHandler(int port, int min, int threshold, int max) {
        this.port = port;
        this.min = min;
        this.threshold = threshold;
        this.max = max;
    }
    
    public void run() {
        MainWindow.window.addLogEntry("Connection Pool Handler started");
        
        try {
            ConnectionPoolConnectionHandler.server_socket = new ServerSocket(this.port);
            
            // While the server socket isn't closed
            while (!ConnectionPoolConnectionHandler.server_socket.isClosed()) {   
                
                // Fill connection pool to it's minimum
                while(MainWindow.available_threads.size() + MainWindow.number_active_threads < min)
                {
                    HTTPHandler temp = new HTTPHandler(null);
                    temp.start();
                    MainWindow.available_threads.add(temp);
                    MainWindow.window.addSleepingThread();
                }
                
                Socket socket = ConnectionPoolConnectionHandler.server_socket.accept();
                
                // If there aren't enough threads then add them
                if(MainWindow.available_threads.size() == 0 && MainWindow.number_active_threads < max) {
                    HTTPHandler temp = new HTTPHandler(null);
                    temp.start();
                    MainWindow.available_threads.add(temp);
                    MainWindow.window.addSleepingThread();
                    
                    // If the threshold has been reached then change the minimum
                    if(MainWindow.available_threads.size() + MainWindow.number_active_threads > threshold)
                        min = threshold;
                        MainWindow.MINIMUM_CONNECTION_POOL = min;
                        MainWindow.window.setSpinnerMinimumValue(threshold);
                    }
                
                // Wait for an available thread (it may have not been possible to create it before
                while(MainWindow.available_threads.size() == 0 && !ConnectionPoolConnectionHandler.server_socket.isClosed())
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                
                if(!ConnectionPoolConnectionHandler.server_socket.isClosed()) {
                    HTTPHandler handler = MainWindow.available_threads.get(0);
                    MainWindow.available_threads.remove(0);
                    MainWindow.window.removeSleepingThread();
                    handler.setSocket(socket);
                }
            }
        } catch (IOException e) {
            System.err.println("ERROR: Problem launching HTTP handling thread.");
        }
        
        MainWindow.window.addLogEntry("Connection Pool Handler stopped");
    }
}
